package com.sse.product.filter;

import com.sse.product.rbac.entity.User;
import com.sse.product.rbac.mapper.UserMapper;
import com.sse.product.model.rbac.LoginUser;
import com.sse.product.util.JwtUtil;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author HP
 * @since 2024/6/19
 */

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Autowired
    private UserMapper userMapper;

    private static final long RENEW_THRESHOLD = 1000 * 60 * 10; // 10 minutes

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        System.out.println("执行过滤器JwtAuthenticationTokenFilter，处理请求前的处理！");
        //获取token，jwt
        String jwtToken = request.getHeader("Authorization");
        if (!StringUtils.hasText(jwtToken) || !JwtUtil.validateToken(jwtToken)) {
            //放行
            filterChain.doFilter(request, response);
            return;
        }
        //解析token
        Claims claims = null;
        try {
            claims = JwtUtil.parseJWT(jwtToken);
        } catch (Exception e) {
            throw new RuntimeException("jwtToken非法！",e);
        }
        String username = claims.getSubject();
        String userid = claims.get("userid", String.class);
        List<String> roles = claims.get("roles", List.class);
        Date expiration = claims.getExpiration();

        // token续期方案思路，设置token过期时间30分钟，每次请求的时候走过滤器判断token是否过期，
        // 如果将要过期取token里用户名重新生成token返回前端，如果已经过期重新跳登录
        long currentTimeMillis = System.currentTimeMillis();
        long timeToExpiration = expiration.getTime() - currentTimeMillis;
        if (timeToExpiration < RENEW_THRESHOLD) {
            User user = userMapper.selectById(userid);
            LoginUser loginUser = new LoginUser(user,null);
            String newToken = JwtUtil.generateJwt(loginUser);
            // 返回给前端
            response.setHeader("Authorization", newToken);
        }

        /*查数据库，确认用户信息：如有需要可以在这里添加*/

        if (username != null && roles != null) {
            //将用户信息存入SecurityContextHolder
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                    new UsernamePasswordAuthenticationToken(
                            username,
                            null,
                            roles.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList()));
            SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
        }
        //放行过滤器链
        filterChain.doFilter(request, response);

        //
        System.out.println("执行过滤器JwtAuthenticationTokenFilter，处理请求后的处理！");
    }
}
